﻿using Microsoft.AspNetCore.Mvc;
using Newtonsoft.Json;
using Quartz;
using Quartz.Impl;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using Treca.Quartz.Quarzt.Enum;
using Treca.Util.BackJob;
using Treca.Util;
using Treca.Quartz.Entity;
using Quartz.Impl.Matchers;
using Treca.Quartz.Business;

namespace Treca.Quartz.Service
{
    /// <summary>
    /// 任务调度中心
    /// </summary>
    public class JobCenter
    {
        public static void Init()
        {
            Ibase_schedulesinfoBusiness schedulesinfoBusiness = AutofacHelper.GetScopeService<Ibase_schedulesinfoBusiness>();
            var list = schedulesinfoBusiness.GetIQueryableAll().Where(t => t.StatusFlag == "1").ToList();
            list.ForEach((x) =>
            {
                AddScheduleJobAsync(x);
            });
        }
        /// <summary>
        /// 任务计划
        /// </summary>
        public static IScheduler scheduler = null;
        public static IScheduler GetScheduler()
        {
            if (scheduler != null)
            {
                return scheduler;
            }
            else
            {
                IScheduler sched = QuartzService._scheduler;
                return sched;
            }
        }
        /// <summary>
        /// 添加任务计划//或者进程终止后的开启
        /// </summary>
        /// <returns></returns>
        public static async Task<bool> AddScheduleJobAsync(base_schedulesinfo m)
        {
            if (m != null)
            {
                if (m.StarRunTime == null)
                {
                    m.StarRunTime = DateTime.Now;
                }
                DateTimeOffset starRunTime = DateBuilder.NextGivenSecondDate(m.StarRunTime, 1);
                if (m.EndRunTime == null)
                {
                    m.EndRunTime = DateTime.MaxValue;
                }
                DateTimeOffset endRunTime = DateBuilder.NextGivenSecondDate(m.EndRunTime, 1);
                scheduler = GetScheduler();
                IJobDetail job = JobBuilder.Create()
                  .WithIdentity(m.JobName, m.JobGroup)
                  .OfType(AutofacHelper.JobType[m.JobClass])
                  .WithDescription(m.JobDesc)
                  .Build();
                ICronTrigger trigger = (ICronTrigger)TriggerBuilder.Create()
                                             .StartAt(starRunTime)
                                             .EndAt(endRunTime)
                                             .WithIdentity(m.JobName, m.JobGroup)
                                             .WithCronSchedule(m.CromExpress, (builder) =>
                                             {
                                                                             builder.WithMisfireHandlingInstructionDoNothing();
                                              })
                                             .ForJob(job)
                                             .Build();
                //await scheduler.DeleteJob(new JobKey(m.JobName,m.JobGroup));
                List<ITrigger> cronTriggers = new List<ITrigger>();
                cronTriggers.Add(trigger);
                await scheduler.ScheduleJob(job, cronTriggers, true);
                //await scheduler.Start();
                //await PauseScheduleJobAsync(m.JobGroup, m.JobName);
                return true;
            }
            return false;
        }

        public static async Task<List<base_schedulesinfo>> GetScheduleJobAllAsync()
        {
            List<base_schedulesinfo> base_Schedulesinfos = new List<base_schedulesinfo>();
            try
            {
                scheduler = GetScheduler();
                var jobkeys = await scheduler.GetJobKeys(GroupMatcher<JobKey>.AnyGroup());
                jobkeys.ForEach((jobkey) =>
                {
                    base_schedulesinfo base_Schedulesinfo = new base_schedulesinfo();
                    var jobinfo = scheduler.GetJobDetail(jobkey);
                    base_Schedulesinfo.JobName = jobinfo.Result.Key.Name;
                    base_Schedulesinfo.JobGroup = jobinfo.Result.Key.Group;
                    base_Schedulesinfo.JobDesc = jobinfo.Result.Description;
                    base_Schedulesinfo.JobClass = jobinfo.Result.JobType.FullName;

                    var triggersinfo = scheduler.GetTriggersOfJob(jobkey);
                    if (triggersinfo.Result.Count > 0)
                    {
                        ICronTrigger s = (ICronTrigger)triggersinfo.Result.Take(1).ToList()[0];
                        TriggerState state = scheduler.GetTriggerState(s.Key).Result;
                        base_Schedulesinfo.RunStatus = state.ToString();
                        base_Schedulesinfo.StarRunTime = s.StartTimeUtc.ToLocalTime().DateTime;
                        base_Schedulesinfo.EndRunTime = s.EndTimeUtc?.ToLocalTime().DateTime;
                        base_Schedulesinfo.PreviousRunTime = s.GetPreviousFireTimeUtc()?.ToLocalTime().DateTime;
                        base_Schedulesinfo.NextRunTime = s.GetNextFireTimeUtc()?.ToLocalTime().DateTime;
                        base_Schedulesinfo.CromExpress = s.CronExpressionString;
                    }
                    base_Schedulesinfos.Add(base_Schedulesinfo);
                });

                return base_Schedulesinfos;
            }
            catch (Exception ex)
            {
                LogHelper.WriteLog_LocalTxt(ExceptionHelper.GetExceptionAllMsg(ex));
                //MyLogger.WriteError(ex, null);
                return base_Schedulesinfos;
            }
        }

        /// <summary>
        /// 暂停指定任务计划
        /// </summary>
        /// <returns></returns>
        public static async Task<AjaxResult> PauseScheduleJobAsync(string jobGroup, string jobName)
        {
            try
            {
                scheduler = GetScheduler();
                //使任务暂停
                await scheduler.PauseJob(new JobKey(jobName, jobGroup));
                //更新数据库
                //new ScheduleManage().UpdateScheduleStatus(new base_schedulesinfo() { JobName = jobName, JobGroup = jobGroup, RunStatus = JobStatus.已停止.ToString() });
                return AjaxHelper.Success("暂停任务计划成功");
            }
            catch (Exception ex)
            {
                return AjaxHelper.Error("暂停任务计划失败" + ex.Message);
            }
        }
        /// <summary>
        /// 恢复指定的任务计划**恢复的是暂停后的任务计划，如果是程序奔溃后 或者是进程杀死后的恢复，此方法无效
        /// </summary>
        /// <returns></returns>
        public static async Task<AjaxResult> ResumeScheduleJobAsync(string jobGroup, string jobName)
        {
            try
            {
                ////获取model
                //var jobs = await GetScheduleJobAllAsync();
                //var sm = jobs.Where(t => t.JobGroup == jobGroup && t.JobName == jobName).FirstOrDefault();
                //await AddScheduleJobAsync(sm);
                //sm.RunStatus = JobStatus.已启用.ToString();
                ////更新model
                ////new ScheduleManage().UpdateScheduleStatus(sm);
                scheduler = GetScheduler();
                //resumejob 恢复
                await scheduler.ResumeJob(new JobKey(jobName, jobGroup));

                return AjaxHelper.Success("开启任务计划成功");
            }
            catch (Exception ex)
            {
                return AjaxHelper.Error("开启任务计划失败" + ex.Message);
            }
        }

        /// <summary>
        /// 执行任务
        /// </summary>
        /// <returns></returns>
        public static async Task<AjaxResult> RunScheduleJobAsync(string jobGroup, string jobName)
        {
            try
            {
                //验证UKEY
                string m_name = Treca.Util.Helper.SoftKey.GetProjectNo();
                if (m_name == "654321")
                {
                    ////获取model
                    //var jobs = await GetScheduleJobAllAsync();
                    //var sm = jobs.Where(t => t.JobGroup == jobGroup && t.JobName == jobName).FirstOrDefault();
                    //await AddScheduleJobAsync(sm);
                    //sm.RunStatus = JobStatus.已启用.ToString();
                    ////更新model
                    ////new ScheduleManage().UpdateScheduleStatus(sm);
                    scheduler = GetScheduler();
                    //resumejob 恢复
                    await scheduler.TriggerJob(new JobKey(jobName, jobGroup));

                    return AjaxHelper.Success("开启任务计划成功");
                }
                else
                {
                    return AjaxHelper.Error("加密狗授权错误，无法开启任务计划");
                }
            }
            catch (Exception ex)
            {
                return AjaxHelper.Error("开启任务计划失败"+ex.Message);
            }
        }
    }
}
